package dto

import (
	"bytes"
	"crypto/sha256"
	"encoding/gob"
	"encoding/hex"
	"encoding/json"
	"osiris/logger"
	//"github.com/davecgh/go-spew/spew"
)

// const 返回code，客户端、以及P2P连接中发起连接的一端的首次通信不需要带code（默认0）
//
//	@param CODE_TERMINATE 连接终止，收到后的一端应在接收完数据后关闭网络流
//	@param CODE_TERMINATE 节点内部发生错误
const (
	CODE_TERMINATE      = -1
	CODE_INTERNAL_ERROR = -2
)

// BaseDto 基础DTO，其它DTO在正常情况下都要嵌套这个
type BaseDto struct {

	// Code 状态码
	Code int `json:"code"`

	// Msg 信息说明
	Msg string `json:"msg"`

	// DtoHash 整个Dto的Hash，具体计算过程根据不同业务场景各自实现
	DtoHash string `json:"dtoHash"`

	// DataMap
	DataMap map[string]string `json:"datamap"`
}

type ErrorDto struct {
	Code    int         `json:"code"`
	Message interface{} `json:"message"`
}

//TODO comfirm: gob编码会不会因为内存映射等非结构体本身的原因导致结果不同？
// ToBytes 通过gob编码将结构体转为[]byte
//
//	@param dto 任意结构体
//	@return []byte
//	@return error
func ToBytes(dto interface{}) ([]byte, error) {
	buf := new(bytes.Buffer)
	encode := gob.NewEncoder(buf)
	if err := encode.Encode(dto); err != nil {
		logger.Error(map[string]interface{}{"[dto] [To Bytes] gob encode": err})
		return make([]byte, 0), err
	}

	return buf.Bytes(), nil
}

// FromBytes 通过gob解码将[]byte转为对应的结构体
//
//	@param data 结构体对应的字节数组
//	@param dto 写入转换后结构体的地址（&dto）
//	@return error
func FromBytes(data []byte, dto interface{}) error {
	buf := bytes.NewReader(data)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(dto)
	if err != nil {
		logger.Error(map[string]interface{}{"[dto] [From Bytes] gob encode": err})
	}

	return err
}

// SHA256Hash 通过SHA256计算结构体的hash
//
//	@param dto
//	@return string hex编码的hash
//	@return error
func SHA256Hash(dto interface{}) (string, error) {
	bytes, err := json.Marshal(dto)
	if err != nil {
		logger.Error(map[string]interface{}{"[dto] [SHA256Hash] json.Marshal()": err})
		return "", nil
	}

	hash := sha256.Sum256(bytes)
	hashString := hex.EncodeToString(hash[:])
	return hashString, nil
}
